package com.zym.application.session;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zym.application.config.SystemConfig;
import com.zym.application.exception.AppBugExcepiton;
import com.zym.application.model.ReturnModel;
import com.zym.application.service.PageService;
import com.zym.application.utils.Qs;
import com.zym.application.utils.StringUtils;
import com.zym.framework.alert.AlertUtils;
import com.zym.framework.notice.NoticeUtils;
import com.zym.framework.progress.ProgressTask;
import com.zym.framework.progress.ProgressUtils;
import javafx.stage.Stage;
import javafx.stage.Window;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * QQ 165149324
 * 臧英明
 *
 * @author
 * @create 2021-01-29
 */
public class Http {
    //会话
    private static final CloseableHttpClient httpclient = HttpClients.createDefault();
    private static final Map httpAges = new HashMap();
    private static final String FAIL_TEXT = "错误，请联系管理员";
    private static SystemConfig systemConfig = SystemConfig.getInstance();
    public static void setCookie(String cookie) {
        httpAges.put("cookie",cookie);
    }
    public static void post(String url, Map map,HttpCall httpCall){
        post(url,map,null,httpCall);
    }

    public static void post(String url, Map map, Window owner, HttpCall httpCall){
        if(owner == null){
            Stage mainStage = PageService.getInstance().getMainStage();
            owner = mainStage.getScene().getWindow();
        }
        //建立任务
        ProgressTask<ReturnModel> progressTask = new ProgressTask() {
            @Override
            protected ReturnModel execute() throws Exception {
                updateInfo(50,100,"请求数据中……");
                ReturnModel returnModel = postNotProgress(url, map);
                updateInfo(100,100,"请求完毕");
                //多线程内跳转会报错。因为此线程调用主线窗口管理会产生冲突
                return returnModel;
            }
        };
        ProgressUtils sb = ProgressUtils.create( owner, progressTask, "网络连接 ");
        sb.showAndWait();
        ReturnModel returnModel1 = null;
        //堵塞 等待子线程返回值
        try {
            returnModel1 = progressTask.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        if(returnModel1 == null){
            throw new  AppBugExcepiton("HTTP请求错误");
        }
        if(returnModel1.isFailed()){
            if(returnModel1.getObj() != null){
                NoticeUtils.error(returnModel1.getObj().toString());
            }else {
                NoticeUtils.error(FAIL_TEXT);
            }
            return;
        }

        //主线程更新页面。
        if(httpCall!=null){
            httpCall.exe(returnModel1);
        }

    }

    public static ReturnModel postNotProgress(String url, Map map){
        ReturnModel returnModel;
        String s = sendPost(systemConfig.getBaseUrl() + url, map);
        returnModel = new ReturnModel();
        if(s.indexOf("[") ==0 && s.lastIndexOf("]") == s.length()-1){
            JSONArray jsonArray = JSONArray.parseArray(s);
            returnModel.setObj(jsonArray);
        }else if(StringUtils.isEmpty(s)){
            return returnModel;
        }else {
            JSONObject jsonObject = JSONObject.parseObject(s);
            if(jsonObject.containsKey("result") && jsonObject.containsKey("obj") &&  jsonObject.containsKey("bean")){
                returnModel = jsonObject.toJavaObject(ReturnModel.class);
            }else {
                returnModel.setObj(jsonObject);
            }

        }
        return  returnModel;
    }
    public static JSONObject postJSONObject(String url, Map map){
        JSONObject jsonObject = JSONObject.parseObject(sendPost(systemConfig.getBaseUrl()+url, map));
        return  jsonObject;
    }
    public static void celarCache(){
        httpAges.clear();
    }


    public static String sendPost(String url,Map map) {
        // 设置参数
        // 编码
        String str = Qs.stringify(map);
        StringEntity stringEntity = new StringEntity(str, Consts.UTF_8);
        // 取得HttpPost对象
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
        if(httpAges.containsKey("Cookie")){
            httpPost.setHeader("Cookie", httpAges.get("Cookie").toString());
        }else {
            celarCache();
        }
        // 防止被当成攻击添加的
        // 参数放入Entity
        httpPost.setEntity(stringEntity);
        CloseableHttpResponse response = null;
        String result = null;
        try {
            // 执行post请求
            response = httpclient.execute(httpPost);
            int statusCode =  response.getStatusLine().getStatusCode();
            if(statusCode == 200){
                if(httpAges.size() == 0){
                    Header[] headers = response.getAllHeaders();
                    for (int i = 0; i < headers.length; i++) {
                        httpAges.put(headers[i].getName(),headers[i].getValue());
                    }
                }
                // 得到entity
                HttpEntity entity = response.getEntity();
                // 得到字符串
                result = EntityUtils.toString(entity);
            }else if(statusCode ==  404 || statusCode ==  302) { //跳转登录
                celarCache();
            }else {
                AlertUtils.error("与服务器连接出现错误!");
            }

        } catch (IOException e) {
            AlertUtils.error("网络连接出错!");
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                }
            }
        }
        return result;
    }
}
